package model.map;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.StringTokenizer;

public class MapMaker
{
	private class TerrainFrequency
	{
		private String terrainType, walkables;
		private int frequency;
		
		public TerrainFrequency(String t, int f, String w)
		{
			terrainType = t;
			frequency = f;
			walkables = w;
		}
		
		public String terrain()
		{
			return terrainType;
		}
		
		public int frequency()
		{
			return frequency;
		}
		
		public boolean allCanWalk()
		{
			return walkables.equals("ALL");
		}
		
		public boolean vehiclesCanWalk()
		{
			return walkables.equals("VEHICLE");
		}
	}
	
	private List<TerrainFrequency> terrainList = new LinkedList<TerrainFrequency>();
	private int frequencyTotal = 0;
	public static final MapMaker mapMaker = new MapMaker("TerrainTypes.txt");
	
	private final int MAP_HEIGHT = 15, MAP_WIDTH = 15;
	
	private MapMaker(String file)
	{
		terrainList = new LinkedList<TerrainFrequency>();
		
		fillTerrainList(file);
	}
	
	private void fillTerrainList(String file)
	{
		
		try
		{
			
			BufferedReader rdr = new BufferedReader(new FileReader(file));
			
			int freq;
			String terName, walk;
			
			while (rdr.ready())
			{
				StringTokenizer tkn = new StringTokenizer(rdr.readLine() + " ");
				
				terName = tkn.nextToken();
				freq = Integer.parseInt(tkn.nextToken());
				walk = tkn.nextToken();
				
				TerrainFrequency tf = new TerrainFrequency(terName, freq, walk);
				frequencyTotal += freq;
				
				terrainList.add(tf);
			}
			
			rdr.close();
			
		} catch (FileNotFoundException e)
		{
			e.printStackTrace();
			System.exit(-1);
		} catch (IOException e)
		{
			e.printStackTrace();
			System.exit(-1);
		} catch (NoSuchElementException e)
		{
			e.printStackTrace();
			System.exit(-1);
		}
	}

	public GameMap getNewMap()
	{
		HexTile[][] tiles = new HexTile[MAP_WIDTH][MAP_HEIGHT];
		
		for (int i = 0; i < MAP_WIDTH; i++)
		{
			for(int j = 0; j < MAP_HEIGHT; j++)
			{
				tiles[i][j] = createNewTile(i, j);
			}
		}
		
		for (int i = 0; i < MAP_WIDTH; i++)
		{
			tiles[i][MAP_HEIGHT/2].setCurrent(new Current(Direction.NW, 1));
		}
		
		GameMap map = new GameMap(tiles);
		
		map.addStartingLocation(2, 2);
		tiles[2][2].setTerrainType(terrainList.get(0).terrain());
		map.addStartingLocation(2, 12);
		tiles[2][12].setTerrainType(terrainList.get(0).terrain());
		
		return map;
	}
	
	public List<String> getTerrainsWalkableByAll()
	{
		List<String> terrains = new LinkedList<String>();
		
		for (TerrainFrequency tf : terrainList)
			if (tf.allCanWalk())
				terrains.add(tf.terrain());
		
		return terrains;
	}
	
	public List<String> getTerrainsWalkableByVehicles()
	{
		List<String> terrains = new LinkedList<String>();
		
		for (TerrainFrequency tf : terrainList)
			if (tf.allCanWalk() || tf.vehiclesCanWalk())
				terrains.add(tf.terrain());
		
		return terrains;
	}

	private HexTile createNewTile(int x, int y)
	{
		String t = getRandomTerrain();
		
		return new HexTile(x, y, t);
	}

	private String getRandomTerrain()
	{
		Random rnd = new Random();
		
		int x = rnd.nextInt(frequencyTotal);
		
		int check = 0;
		
		for (TerrainFrequency tf : terrainList)
		{
			check += tf.frequency();
			
			if (x < check)
				return tf.terrain();
		}
		
		if (check > frequencyTotal)
		{
			throw new RuntimeException("How the hell did check go over the frequencyTotal?!");
		}
		
		return "NULL";
	}
}
